#include "TransientDirectSolver.h"

#include "Utility/Algebra/Factory.h"
#include "Utility/Algebra/TimeSteppers.h"
#include "Utility/Configuration/SGParameter.h"
#include "Utility/Logging/SGLogger.h"

#include "DataStructure/Input/Solver/Subcase.h"

#include "DBManager/IService/Input/Subcase/ISubcaseService.h"

#include "SGFem/Pre/Assembly/Assembly.h"

#include "SGFem/Task/Kernel/MModel.h"

using SG::DataStructure::Common::Status;
using SG::DataStructure::FEM::InitConditonType;
using SG::DataStructure::FEM::Project;
using SG::DataStructure::FEM::SOLType;
using namespace SG::DBManager;

void TransientDirectSolver::Solve (const DBServiceFactorySP dbServiceFactory, const Project& project, int subcaseId)
{
    Kernel::MModel modal (SOLType::SOL_SEDTRAN, dbServiceFactory);

    /** ToDo 检查求解必须设置的参数是否完备
     *
     * 是否正确初始化？
     * 积分时间间隔为 0.0. 导致矩阵奇异怎么办？
     * @author   wanghuan
     * @date     2025.07.16
     */
    auto                            para = dbServiceFactory->get<ISubcaseService> ()->FindSubCase (subcaseId);
    SG::DataStructure::FEM::Subcase subcase (para);

    const auto                                   tStepId = subcase.GetTSTEPId ();
    std::vector<SG::DataStructure::Common::Real> t;
    std::vector<SG::DataStructure::Common::Real> tOut;
    modal.QueryTimeStep (tStepId, t, tOut);
    if (0 == t.size())
    {
        return;
    }

    // 单元计算
    modal.Initialize ({ subcaseId });
    modal.CalcMatrixEquation (subcaseId);


    // 初始化位移向量 U 和速度向量 V
    // auto&              assembly = SG::FEMSolver::AssemblyEigen::GetInstance ();

    InitConditonType   type;
    auto               initId = subcase.GetICId (type);
    SG::Algebra::Vec_t U, V, A;
    modal.ComputeInitialCondition (initId, type, U, V);

    modal.ComputeFValue (subcaseId);  // 计算静荷载向量

    // 时间积分器
    void* solver = SG::Base::Factory::GetInstance ()->Produce ("ModifiedCentralDifference");
    auto  Solver = reinterpret_cast<SG::Algebra::SecondOrderTimeStepper*> (solver);
    Solver->Initialize (&modal);

    // 0 时刻
    modal.SetDisplacement (U, subcaseId, 0.0);

    // t 时刻
    for (size_t i = 1; i < t.size (); ++i)
    {
        Solver->SetTime (t[i]);
        Solver->SetTimeStep (t[i] - t[i - 1]);

        Solver->Step (U, V, A);

        // ToDo 并不是每一步都需要保存
        modal.SetDisplacement (U, subcaseId, t[i]);
    }

    SGInfo << "DirectTransientAnalysis Solve fini  \n";
}